/**
 * Handler控制模块
 * @module zrender/Handler
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *         errorrik (errorrik@gmail.com)
 *
 */
// TODO mouseover 只触发一次
// 目前的高亮因为每次都需要 addHover 所以不能只是开始的时候触发一次


'use strict';
var config = require('./config');
var env = require('./tool/env');
var eventTool = require('./tool/event');
var util = require('./tool/util');
var vec2 = require('./tool/vector');
var mat2d = require('./tool/matrix');
var EVENT = config.EVENT;
var Eventful = require('./mixin/Eventful');
var domHandlerNames = [
    'resize',
    'click',
    'dblclick',
    'mousewheel',
    'mousemove',
    'mouseout',
    'mouseup',
    'mousedown',
    'touchstart',
    'touchend',
    'touchmove'
];
var isZRenderElement = function (event) {
    // 暂时忽略 IE8-
    if (window.G_vmlCanvasManager) {
        return true;
    }
    event = event || window.event;
    // 进入对象优先~
    var target = event.toElement || event.relatedTarget || event.srcElement || event.target;
    return target && target.className.match(config.elementClassName);
};
var domHandlers = {
    /**
             * 窗口大小改变响应函数
             * @inner
             * @param {Event} event
             */
    resize: function (event) {
        event = event || window.event;
        this._lastHover = null;
        this._isMouseDown = 0;
        // 分发config.EVENT.RESIZE事件，global
        this.dispatch(EVENT.RESIZE, event);
    },
    /**
             * 点击响应函数
             * @inner
             * @param {Event} event
             */
    click: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = this._zrenderEventFixed(event);
        // 分发config.EVENT.CLICK事件
        var _lastHover = this._lastHover;
        if (_lastHover && _lastHover.clickable || !_lastHover) {
            // 判断没有发生拖拽才触发click事件
            if (this._clickThreshold < 5) {
                this._dispatchAgency(_lastHover, EVENT.CLICK, event);
            }
        }
        this._mousemoveHandler(event);
    },
    /**
             * 双击响应函数
             * @inner
             * @param {Event} event
             */
    dblclick: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = event || window.event;
        event = this._zrenderEventFixed(event);
        // 分发config.EVENT.DBLCLICK事件
        var _lastHover = this._lastHover;
        if (_lastHover && _lastHover.clickable || !_lastHover) {
            // 判断没有发生拖拽才触发dblclick事件
            if (this._clickThreshold < 5) {
                this._dispatchAgency(_lastHover, EVENT.DBLCLICK, event);
            }
        }
        this._mousemoveHandler(event);
    },
    /**
             * 鼠标滚轮响应函数
             * @inner
             * @param {Event} event
             */
    mousewheel: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = this._zrenderEventFixed(event);
        // http://www.sitepoint.com/html5-javascript-mouse-wheel/
        // https://developer.mozilla.org/en-US/docs/DOM/DOM_event_reference/mousewheel
        var delta = event.wheelDelta || -event.detail;
        // Firefox
        var scale = delta > 0 ? 1.1 : 1 / 1.1;
        var needsRefresh = false;
        var mouseX = this._mouseX;
        var mouseY = this._mouseY;
        this.painter.eachBuildinLayer(function (layer) {
            var pos = layer.position;
            if (layer.zoomable) {
                layer.__zoom = layer.__zoom || 1;
                var newZoom = layer.__zoom;
                newZoom *= scale;
                newZoom = Math.max(Math.min(layer.maxZoom, newZoom), layer.minZoom);
                scale = newZoom / layer.__zoom;
                layer.__zoom = newZoom;
                // Keep the mouse center when scaling
                pos[0] -= (mouseX - pos[0]) * (scale - 1);
                pos[1] -= (mouseY - pos[1]) * (scale - 1);
                layer.scale[0] *= scale;
                layer.scale[1] *= scale;
                layer.dirty = true;
                needsRefresh = true;
                // Prevent browser default scroll action 
                eventTool.stop(event);
            }
        });
        if (needsRefresh) {
            this.painter.refresh();
        }
        // 分发config.EVENT.MOUSEWHEEL事件
        this._dispatchAgency(this._lastHover, EVENT.MOUSEWHEEL, event);
        this._mousemoveHandler(event);
    },
    /**
             * 鼠标（手指）移动响应函数
             * @inner
             * @param {Event} event
             */
    mousemove: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        if (this.painter.isLoading()) {
            return;
        }
        event = this._zrenderEventFixed(event);
        this._lastX = this._mouseX;
        this._lastY = this._mouseY;
        this._mouseX = eventTool.getX(event);
        this._mouseY = eventTool.getY(event);
        var dx = this._mouseX - this._lastX;
        var dy = this._mouseY - this._lastY;
        // 可能出现config.EVENT.DRAGSTART事件
        // 避免手抖点击误认为拖拽
        // if (this._mouseX - this._lastX > 1 || this._mouseY - this._lastY > 1) {
        this._processDragStart(event);
        // }
        this._hasfound = 0;
        this._event = event;
        this._iterateAndFindHover();
        // 找到的在迭代函数里做了处理，没找到得在迭代完后处理
        if (!this._hasfound) {
            // 过滤首次拖拽产生的mouseout和dragLeave
            if (!this._draggingTarget || this._lastHover && this._lastHover != this._draggingTarget) {
                // 可能出现config.EVENT.MOUSEOUT事件
                this._processOutShape(event);
                // 可能出现config.EVENT.DRAGLEAVE事件
                this._processDragLeave(event);
            }
            this._lastHover = null;
            this.storage.delHover();
            this.painter.clearHover();
        }
        // set cursor for root element
        var cursor = 'default';
        // 如果存在拖拽中元素，被拖拽的图形元素最后addHover
        if (this._draggingTarget) {
            this.storage.drift(this._draggingTarget.id, dx, dy);
            this._draggingTarget.modSelf();
            this.storage.addHover(this._draggingTarget);
            // 拖拽不触发click事件
            this._clickThreshold++;
        } else if (this._isMouseDown) {
            var needsRefresh = false;
            // Layer dragging
            this.painter.eachBuildinLayer(function (layer) {
                if (layer.panable) {
                    // PENDING
                    cursor = 'move';
                    // Keep the mouse center when scaling
                    layer.position[0] += dx;
                    layer.position[1] += dy;
                    needsRefresh = true;
                    layer.dirty = true;
                }
            });
            if (needsRefresh) {
                this.painter.refresh();
            }
        }
        if (this._draggingTarget || this._hasfound && this._lastHover.draggable) {
            cursor = 'move';
        } else if (this._hasfound && this._lastHover.clickable) {
            cursor = 'pointer';
        }
        this.root.style.cursor = cursor;
        // 分发config.EVENT.MOUSEMOVE事件
        this._dispatchAgency(this._lastHover, EVENT.MOUSEMOVE, event);
        if (this._draggingTarget || this._hasfound || this.storage.hasHoverShape()) {
            this.painter.refreshHover();
        }
    },
    /**
             * 鼠标（手指）离开响应函数
             * @inner
             * @param {Event} event
             */
    mouseout: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = this._zrenderEventFixed(event);
        var element = event.toElement || event.relatedTarget;
        if (element != this.root) {
            while (element && element.nodeType != 9) {
                // 忽略包含在root中的dom引起的mouseOut
                if (element == this.root) {
                    this._mousemoveHandler(event);
                    return;
                }
                element = element.parentNode;
            }
        }
        event.zrenderX = this._lastX;
        event.zrenderY = this._lastY;
        this.root.style.cursor = 'default';
        this._isMouseDown = 0;
        this._processOutShape(event);
        this._processDrop(event);
        this._processDragEnd(event);
        if (!this.painter.isLoading()) {
            this.painter.refreshHover();
        }
        this.dispatch(EVENT.GLOBALOUT, event);
    },
    /**
             * 鼠标（手指）按下响应函数
             * @inner
             * @param {Event} event
             */
    mousedown: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        // 重置 clickThreshold
        this._clickThreshold = 0;
        if (this._lastDownButton == 2) {
            this._lastDownButton = event.button;
            this._mouseDownTarget = null;
            // 仅作为关闭右键菜单使用
            return;
        }
        this._lastMouseDownMoment = new Date();
        event = this._zrenderEventFixed(event);
        this._isMouseDown = 1;
        // 分发config.EVENT.MOUSEDOWN事件
        this._mouseDownTarget = this._lastHover;
        this._dispatchAgency(this._lastHover, EVENT.MOUSEDOWN, event);
        this._lastDownButton = event.button;
    },
    /**
             * 鼠标（手指）抬起响应函数
             * @inner
             * @param {Event} event
             */
    mouseup: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = this._zrenderEventFixed(event);
        this.root.style.cursor = 'default';
        this._isMouseDown = 0;
        this._mouseDownTarget = null;
        // 分发config.EVENT.MOUSEUP事件
        this._dispatchAgency(this._lastHover, EVENT.MOUSEUP, event);
        this._processDrop(event);
        this._processDragEnd(event);
    },
    /**
             * Touch开始响应函数
             * @inner
             * @param {Event} event
             */
    touchstart: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        // eventTool.stop(event);// 阻止浏览器默认事件，重要
        event = this._zrenderEventFixed(event, true);
        this._lastTouchMoment = new Date();
        // 平板补充一次findHover
        this._mobileFindFixed(event);
        this._mousedownHandler(event);
    },
    /**
             * Touch移动响应函数
             * @inner
             * @param {Event} event
             */
    touchmove: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        event = this._zrenderEventFixed(event, true);
        this._mousemoveHandler(event);
        if (this._isDragging) {
            eventTool.stop(event);    // 阻止浏览器默认事件，重要
        }
    },
    /**
             * Touch结束响应函数
             * @inner
             * @param {Event} event
             */
    touchend: function (event, manually) {
        if (!isZRenderElement(event) && !manually) {
            return;
        }
        // eventTool.stop(event);// 阻止浏览器默认事件，重要
        event = this._zrenderEventFixed(event, true);
        this._mouseupHandler(event);
        var now = new Date();
        if (now - this._lastTouchMoment < EVENT.touchClickDelay) {
            this._mobileFindFixed(event);
            this._clickHandler(event);
            if (now - this._lastClickMoment < EVENT.touchClickDelay / 2) {
                this._dblclickHandler(event);
                if (this._lastHover && this._lastHover.clickable) {
                    eventTool.stop(event);    // 阻止浏览器默认事件，重要
                }
            }
            this._lastClickMoment = now;
        }
        this.painter.clearHover();
    }
};
/**
         * bind一个参数的function
         * 
         * @inner
         * @param {Function} handler 要bind的function
         * @param {Object} context 运行时this环境
         * @return {Function}
         */
// function bind1Arg(handler, context) {
//     return function (e) {
//         return handler.call(context, e);
//     };
// }
function bind2Arg(handler, context) {
    return function (arg1, arg2) {
        return handler.call(context, arg1, arg2);
    };
}
function bind3Arg(handler, context) {
    return function (arg1, arg2, arg3) {
        return handler.call(context, arg1, arg2, arg3);
    };
}
/**
         * 为控制类实例初始化dom 事件处理函数
         * 
         * @inner
         * @param {module:zrender/Handler} instance 控制类实例
         */
function initDomHandler(instance) {
    var len = domHandlerNames.length;
    while (len--) {
        var name = domHandlerNames[len];
        instance['_' + name + 'Handler'] = bind2Arg(domHandlers[name], instance);
    }
}
/**
         * @alias module:zrender/Handler
         * @constructor
         * @extends module:zrender/mixin/Eventful
         * @param {HTMLElement} root 绘图区域
         * @param {module:zrender/Storage} storage Storage实例
         * @param {module:zrender/Painter} painter Painter实例
         */
var Handler = function (root, storage, painter) {
    // 添加事件分发器特性
    Eventful.call(this);
    this.root = root;
    this.storage = storage;
    this.painter = painter;
    // 各种事件标识的私有变量
    // this._hasfound = false;              //是否找到hover图形元素
    // this._lastHover = null;              //最后一个hover图形元素
    // this._mouseDownTarget = null;
    // this._draggingTarget = null;         //当前被拖拽的图形元素
    // this._isMouseDown = false;
    // this._isDragging = false;
    // this._lastMouseDownMoment;
    // this._lastTouchMoment;
    // this._lastDownButton;
    this._lastX = this._lastY = this._mouseX = this._mouseY = 0;
    this._findHover = bind3Arg(findHover, this);
    this._domHover = painter.getDomHover();
    initDomHandler(this);
    // 初始化，事件绑定，支持的所有事件都由如下原生事件计算得来
    if (window.addEventListener) {
        window.addEventListener('resize', this._resizeHandler);
        if (env.os.tablet || env.os.phone) {
            // mobile支持
            root.addEventListener('touchstart', this._touchstartHandler);
            root.addEventListener('touchmove', this._touchmoveHandler);
            root.addEventListener('touchend', this._touchendHandler);
        } else {
            // mobile的click/move/up/down自己模拟
            root.addEventListener('click', this._clickHandler);
            root.addEventListener('dblclick', this._dblclickHandler);
            root.addEventListener('mousewheel', this._mousewheelHandler);
            root.addEventListener('mousemove', this._mousemoveHandler);
            root.addEventListener('mousedown', this._mousedownHandler);
            root.addEventListener('mouseup', this._mouseupHandler);
        }
        root.addEventListener('DOMMouseScroll', this._mousewheelHandler);
        root.addEventListener('mouseout', this._mouseoutHandler);
    } else {
        window.attachEvent('onresize', this._resizeHandler);
        root.attachEvent('onclick', this._clickHandler);
        //root.attachEvent('ondblclick ', this._dblclickHandler);
        root.ondblclick = this._dblclickHandler;
        root.attachEvent('onmousewheel', this._mousewheelHandler);
        root.attachEvent('onmousemove', this._mousemoveHandler);
        root.attachEvent('onmouseout', this._mouseoutHandler);
        root.attachEvent('onmousedown', this._mousedownHandler);
        root.attachEvent('onmouseup', this._mouseupHandler);
    }
};
/**
         * 自定义事件绑定
         * @param {string} eventName 事件名称，resize，hover，drag，etc~
         * @param {Function} handler 响应函数
         * @param {Object} [context] 响应函数
         */
Handler.prototype.on = function (eventName, handler, context) {
    this.bind(eventName, handler, context);
    return this;
};
/**
         * 自定义事件解绑
         * @param {string} eventName 事件名称，resize，hover，drag，etc~
         * @param {Function} handler 响应函数
         */
Handler.prototype.un = function (eventName, handler) {
    this.unbind(eventName, handler);
    return this;
};
/**
         * 事件触发
         * @param {string} eventName 事件名称，resize，hover，drag，etc~
         * @param {event=} eventArgs event dom事件对象
         */
Handler.prototype.trigger = function (eventName, eventArgs) {
    switch (eventName) {
    case EVENT.RESIZE:
    case EVENT.CLICK:
    case EVENT.DBLCLICK:
    case EVENT.MOUSEWHEEL:
    case EVENT.MOUSEMOVE:
    case EVENT.MOUSEDOWN:
    case EVENT.MOUSEUP:
    case EVENT.MOUSEOUT:
        this['_' + eventName + 'Handler'](eventArgs, true);
        break;
    }
};
/**
         * 释放，解绑所有事件
         */
Handler.prototype.dispose = function () {
    var root = this.root;
    if (window.removeEventListener) {
        window.removeEventListener('resize', this._resizeHandler);
        if (env.os.tablet || env.os.phone) {
            // mobile支持
            root.removeEventListener('touchstart', this._touchstartHandler);
            root.removeEventListener('touchmove', this._touchmoveHandler);
            root.removeEventListener('touchend', this._touchendHandler);
        } else {
            // mobile的click自己模拟
            root.removeEventListener('click', this._clickHandler);
            root.removeEventListener('dblclick', this._dblclickHandler);
            root.removeEventListener('mousewheel', this._mousewheelHandler);
            root.removeEventListener('mousemove', this._mousemoveHandler);
            root.removeEventListener('mousedown', this._mousedownHandler);
            root.removeEventListener('mouseup', this._mouseupHandler);
        }
        root.removeEventListener('DOMMouseScroll', this._mousewheelHandler);
        root.removeEventListener('mouseout', this._mouseoutHandler);
    } else {
        window.detachEvent('onresize', this._resizeHandler);
        root.detachEvent('onclick', this._clickHandler);
        root.detachEvent('dblclick', this._dblclickHandler);
        root.detachEvent('onmousewheel', this._mousewheelHandler);
        root.detachEvent('onmousemove', this._mousemoveHandler);
        root.detachEvent('onmouseout', this._mouseoutHandler);
        root.detachEvent('onmousedown', this._mousedownHandler);
        root.detachEvent('onmouseup', this._mouseupHandler);
    }
    this.root = this._domHover = this.storage = this.painter = null;
    this.un();
};
/**
         * 拖拽开始
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDragStart = function (event) {
    var _lastHover = this._lastHover;
    if (this._isMouseDown && _lastHover && _lastHover.draggable && !this._draggingTarget && this._mouseDownTarget == _lastHover) {
        // 拖拽点击生效时长阀门，某些场景需要降低拖拽敏感度
        if (_lastHover.dragEnableTime && new Date() - this._lastMouseDownMoment < _lastHover.dragEnableTime) {
            return;
        }
        var _draggingTarget = _lastHover;
        this._draggingTarget = _draggingTarget;
        this._isDragging = 1;
        _draggingTarget.invisible = true;
        this.storage.mod(_draggingTarget.id);
        // 分发config.EVENT.DRAGSTART事件
        this._dispatchAgency(_draggingTarget, EVENT.DRAGSTART, event);
        this.painter.refresh();
    }
};
/**
         * 拖拽进入目标元素
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDragEnter = function (event) {
    if (this._draggingTarget) {
        // 分发config.EVENT.DRAGENTER事件
        this._dispatchAgency(this._lastHover, EVENT.DRAGENTER, event, this._draggingTarget);
    }
};
/**
         * 拖拽在目标元素上移动
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDragOver = function (event) {
    if (this._draggingTarget) {
        // 分发config.EVENT.DRAGOVER事件
        this._dispatchAgency(this._lastHover, EVENT.DRAGOVER, event, this._draggingTarget);
    }
};
/**
         * 拖拽离开目标元素
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDragLeave = function (event) {
    if (this._draggingTarget) {
        // 分发config.EVENT.DRAGLEAVE事件
        this._dispatchAgency(this._lastHover, EVENT.DRAGLEAVE, event, this._draggingTarget);
    }
};
/**
         * 拖拽在目标元素上完成
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDrop = function (event) {
    if (this._draggingTarget) {
        this._draggingTarget.invisible = false;
        this.storage.mod(this._draggingTarget.id);
        this.painter.refresh();
        // 分发config.EVENT.DROP事件
        this._dispatchAgency(this._lastHover, EVENT.DROP, event, this._draggingTarget);
    }
};
/**
         * 拖拽结束
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processDragEnd = function (event) {
    if (this._draggingTarget) {
        // 分发config.EVENT.DRAGEND事件
        this._dispatchAgency(this._draggingTarget, EVENT.DRAGEND, event);
        this._lastHover = null;
    }
    this._isDragging = 0;
    this._draggingTarget = null;
};
/**
         * 鼠标在某个图形元素上移动
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processOverShape = function (event) {
    // 分发config.EVENT.MOUSEOVER事件
    this._dispatchAgency(this._lastHover, EVENT.MOUSEOVER, event);
};
/**
         * 鼠标离开某个图形元素
         * 
         * @private
         * @param {Object} event 事件对象
         */
Handler.prototype._processOutShape = function (event) {
    // 分发config.EVENT.MOUSEOUT事件
    this._dispatchAgency(this._lastHover, EVENT.MOUSEOUT, event);
};
/**
         * 事件分发代理
         * 
         * @private
         * @param {Object} targetShape 目标图形元素
         * @param {string} eventName 事件名称
         * @param {Object} event 事件对象
         * @param {Object=} draggedShape 拖拽事件特有，当前被拖拽图形元素
         */
Handler.prototype._dispatchAgency = function (targetShape, eventName, event, draggedShape) {
    var eventHandler = 'on' + eventName;
    var eventPacket = {
        type: eventName,
        event: event,
        target: targetShape,
        cancelBubble: false
    };
    var el = targetShape;
    if (draggedShape) {
        eventPacket.dragged = draggedShape;
    }
    while (el) {
        el[eventHandler] && (eventPacket.cancelBubble = el[eventHandler](eventPacket));
        el.dispatch(eventName, eventPacket);
        el = el.parent;
        if (eventPacket.cancelBubble) {
            break;
        }
    }
    if (targetShape) {
        // 冒泡到顶级 zrender 对象
        if (!eventPacket.cancelBubble) {
            this.dispatch(eventName, eventPacket);
        }
    } else if (!draggedShape) {
        // 无hover目标，无拖拽对象，原生事件分发
        var eveObj = {
            type: eventName,
            event: event
        };
        this.dispatch(eventName, eveObj);
        // 分发事件到用户自定义层
        this.painter.eachOtherLayer(function (layer) {
            if (typeof layer[eventHandler] == 'function') {
                layer[eventHandler](eveObj);
            }
            if (layer.dispatch) {
                layer.dispatch(eventName, eveObj);
            }
        });
    }
};
/**
         * 迭代寻找hover shape
         * @private
         * @method
         */
Handler.prototype._iterateAndFindHover = function () {
    var invTransform = mat2d.create();
    return function () {
        var list = this.storage.getShapeList();
        var currentZLevel;
        var currentLayer;
        var tmp = [
            0,
            0
        ];
        for (var i = list.length - 1; i >= 0; i--) {
            var shape = list[i];
            if (currentZLevel !== shape.zlevel) {
                currentLayer = this.painter.getLayer(shape.zlevel, currentLayer);
                tmp[0] = this._mouseX;
                tmp[1] = this._mouseY;
                if (currentLayer.needTransform) {
                    mat2d.invert(invTransform, currentLayer.transform);
                    vec2.applyTransform(tmp, tmp, invTransform);
                }
            }
            if (this._findHover(shape, tmp[0], tmp[1])) {
                break;
            }
        }
    };
}();
// touch指尖错觉的尝试偏移量配置
var MOBILE_TOUCH_OFFSETS = [
    { x: 10 },
    { x: -20 },
    {
        x: 10,
        y: 10
    },
    { y: -20 }
];
// touch有指尖错觉，四向尝试，让touch上的点击更好触发事件
Handler.prototype._mobileFindFixed = function (event) {
    this._lastHover = null;
    this._mouseX = event.zrenderX;
    this._mouseY = event.zrenderY;
    this._event = event;
    this._iterateAndFindHover();
    for (var i = 0; !this._lastHover && i < MOBILE_TOUCH_OFFSETS.length; i++) {
        var offset = MOBILE_TOUCH_OFFSETS[i];
        offset.x && (this._mouseX += offset.x);
        offset.y && (this._mouseY += offset.y);
        this._iterateAndFindHover();
    }
    if (this._lastHover) {
        event.zrenderX = this._mouseX;
        event.zrenderY = this._mouseY;
    }
};
/**
         * 迭代函数，查找hover到的图形元素并即时做些事件分发
         * 
         * @inner
         * @param {Object} shape 图形元素
         * @param {number} x
         * @param {number} y
         */
function findHover(shape, x, y) {
    if (this._draggingTarget && this._draggingTarget.id == shape.id || shape.isSilent()    // 打酱油的路过，啥都不响应的shape~
) {
        return false;
    }
    var event = this._event;
    if (shape.isCover(x, y)) {
        if (shape.hoverable) {
            this.storage.addHover(shape);
        }
        // 查找是否在 clipShape 中
        var p = shape.parent;
        while (p) {
            if (p.clipShape && !p.clipShape.isCover(this._mouseX, this._mouseY)) {
                // 已经被祖先 clip 掉了
                return false;
            }
            p = p.parent;
        }
        if (this._lastHover != shape) {
            this._processOutShape(event);
            // 可能出现config.EVENT.DRAGLEAVE事件
            this._processDragLeave(event);
            this._lastHover = shape;
            // 可能出现config.EVENT.DRAGENTER事件
            this._processDragEnter(event);
        }
        this._processOverShape(event);
        // 可能出现config.EVENT.DRAGOVER
        this._processDragOver(event);
        this._hasfound = 1;
        return true;    // 找到则中断迭代查找
    }
    return false;
}
/**
         * 如果存在第三方嵌入的一些dom触发的事件，或touch事件，需要转换一下事件坐标
         * 
         * @private
         */
Handler.prototype._zrenderEventFixed = function (event, isTouch) {
    if (event.zrenderFixed) {
        return event;
    }
    if (!isTouch) {
        event = event || window.event;
        // 进入对象优先~
        var target = event.toElement || event.relatedTarget || event.srcElement || event.target;
        if (target && target != this._domHover) {
            event.zrenderX = (typeof event.offsetX != 'undefined' ? event.offsetX : event.layerX) + target.offsetLeft;
            event.zrenderY = (typeof event.offsetY != 'undefined' ? event.offsetY : event.layerY) + target.offsetTop;
        }
    } else {
        var touch = event.type != 'touchend' ? event.targetTouches[0] : event.changedTouches[0];
        if (touch) {
            var rBounding = this.painter._domRoot.getBoundingClientRect();
            // touch事件坐标是全屏的~
            event.zrenderX = touch.clientX - rBounding.left;
            event.zrenderY = touch.clientY - rBounding.top;
        }
    }
    event.zrenderFixed = 1;
    return event;
};
util.merge(Handler.prototype, Eventful.prototype, true);
module.exports = Handler || module.exports;;